// dama_logic

#include <stdlib.h>
#include <stdio.h>

#include "dama_data.h"
#include "dama_logic.h"


int evalPreConditions(move_message_t *proposal, char board[9][9])
{
	int startX = proposal->startX;
	int startY = proposal->startY;
	int endX = proposal->endX;
	int endY = proposal->endY;
	
	printf("Valuto precondizioni\n");
	if(board[startX][startY] != proposal->playerMoving)
		return -1;
	if(board[endX][endY] != 'e'){
		return -1;
	}else return 0;
}

int mustEat(char player, int startX, int startY, char board[9][9])
{
	int result = 0;
	
	printf("Valuto se devo mangiare\n");
	if(player == 'w' && board[startX][startY] == 'b')
	{
		if(board[startX-1][startY-1] == 'w' && board[startX+1][startY+1] == 'e')
		{
			result = (startX+1)*10+startY+1;
		}else if(board[startX+1][startY-1] == 'w' && board[startX-1][startY+1] == 'e')
		{
			result = (startX-1)*10+startY+1;
		}
	}else if(player == 'b' && board[startX][startY] == 'w')
	{
		if(board[startX+1][startY+1] == 'b' && board[startX-1][startY-1] == 'e')
		{
			result = (startX-1)*10+startY-1;
		}else if(board[startX-1][startY+1] == 'b' && board[startX+1][startY-1] == 'e')
		{
			result = (startX+1)*10+startY-1;
		}
	}else if((player == 'W') && (board[startX][startY] == 'b' || board[startX][startY] == 'B'))
	{
		if(board[startX-1][startY-1] == 'W' && board[startX+1][startY+1] == 'e')
		{
			result = (startX+1)*10+startY+1;
		}else if(board[startX+1][startY-1] == 'W' && board[startX-1][startY+1] == 'e')
		{
			result = (startX-1)*10+startY+1;
		}else if(board[startX+1][startY+1] == 'W' && board[startX-1][startY-1] == 'e')
		{
			result = (startX-1)*10+startY-1;
		}else if(board[startX-1][startY+1] == 'W' && board[startX+1][startY-1] == 'e')
		{
			result = (startX+1)*10+startY-1;
		}
	}else if((player == 'B') && (board[startX][startY] == 'w' || board[startX][startY] == 'W'))
	{
		if(board[startX-1][startY-1] == 'B' && board[startX+1][startY+1] == 'e')
		{
			result = (startX+1)*10+startY+1;
		}else if(board[startX+1][startY-1] == 'B' && board[startX-1][startY+1] == 'e')
		{
			result = (startX-1)*10+startY+1;
		}else if(board[startX+1][startY+1] == 'B' && board[startX-1][startY-1] == 'e')
		{
			result = (startX-1)*10+startY-1;
		}else if(board[startX-1][startY+1] == 'B' && board[startX+1][startY-1] == 'e')
		{
			result = (startX+1)*10+startY-1;
		}
	}
	printf("devo mangiare %d\n", result);
	return result;
}

int evalEat(move_message_t *proposal, match_t *m)
{
	int startX = proposal->startX;
	int startY = proposal->startY;
	int lastX = m->lastmoveX;
	int lastY = m->lastmoveY;
	int walk, walk1, walk2, walk3, walk4;
		
	walk = mustEat(proposal->playerMoving, lastX, lastY, m->board);
	walk1 = mustEat(proposal->playerMoving, startX+1, startY+1, m->board);
	walk2 = mustEat(proposal->playerMoving, startX+1, startY-1, m->board);
	walk3 = mustEat(proposal->playerMoving, startX-1, startY+1, m->board);
	walk4 = mustEat(proposal->playerMoving, startX-1, startY-1, m->board);
	
	walk = walk1+walk2+walk3+walk4; 
	printf("Valutato se devo mangiare\n");
	
	return walk;
}

int canMove(move_message_t *proposal, int mustEat, char board[9][9])
{
	int startX = proposal->startX;
	int startY = proposal->startY;
	int endX = proposal->endX;
	int endY = proposal->endY;
	int result = -1;
	printf("startX %d startY %d %d %d \n", startX, startY, endX, endY);
	
	printf("Valuto se la mossa è coerente con precondizioni e con obblighi\n");
	if(mustEat != 0)
	{
		int eatcellX = startX + (endX-startX)/2;
		int eatcellY = startY + (endY-startY)/2;
		switch(board[startX][startY])
		{
		case 'w':
			if(board[eatcellX][eatcellY] == 'b' && board[endX][endY] == 'e' && 
				((startY-endY == 2) || (startY-endY == -2)) && (endX-startX== 2))
			{
				result = (eatcellX*10)+eatcellY;
			}else result = 0;
			break;
		case 'b':		
			if(board[eatcellX][eatcellY] == 'w' && board[endX][endY] == 'e' && 
				((startX-endX == 2) || (startX-endX == -2)) && (startY-endY == 2))
			{
				result = (eatcellX*10)+eatcellY;
			}else result = 0;
			break;
		case 'W':
			if((board[eatcellY][eatcellX] == 'b' || board[eatcellY][eatcellX] == 'B')
				&& board[endY][endX] == 'e' && ((startY-endX == 2) || (startY-endX == -2))
				&& ((endX-startX == 2) || (endX-startX == -2)))
			{
				result = (eatcellX*10)+eatcellY;
			} else result = 0;
			break;
		case 'B':
			if((board[eatcellY][eatcellX] == 'w' || board[eatcellY][eatcellX] == 'W')
				&& board[endY][endX] == 'e' && ((startY-endX == 2) || (startY-endX == -2))
				&& ((endX-startX == 2) || (endX-startX == -2)))
			{
				result = (eatcellX*10)+eatcellY;
			}else result = 0;
			break;
		default:
			break;
		}
	}else{
		switch(board[startX][startY])
		{
		case 'w':
			if((endX - startX == 1) && ((endY - startY == 1)
				|| (endY - startY == -1)))
			{
				result = -1;
			}else result = 0;
			break;
		case 'b':		
			if((endX - startX == -1) && ((endY - startY == 1)
				|| (endY - startY == -1)))
			{
				result = -1;
			}else result = 0;
			break;
		default:
			if(((endX - startX == 1) && ((endY - startY == 1)
				|| (endY - startY == -1))) || ((endX - startX == -1)
				&& ((endY - startY == 1) || (endY - startY == -1))))
			{
				result = -1;
			}else result = 0;
		}
	}
	printf("ho valutato: %d\n", result);
	return result;
}

// Controllo se è possibile continuare a mangiare, eventualmente modifico la flag
// di proposal per segnalarlo
void canEatMore(move_message_t *p, match_t *m)
{
	printf("Valuto se posso continuare a muovere mangiando..\n");
	switch(p->playerMoving)
	{
		case 'w':
			if(m->board[p->endX+1][p->endY+1] == 'b' &&
				m->board[p->endX+2][p->endY+2] == 'e')
			{
				p->flag = 1;
				m->lastmoveX = p->endX+1;
				m->lastmoveY = p->endY+1;
			}else if(m->board[p->endX+1][p->endY-1] == 'b' &&
					m->board[p->endX+2][p->endY-2] == 'e')
			{
				p->flag = 1;
				m->lastmoveX = p->endX+1;
				m->lastmoveY = p->endY-1;
			}
			break;
		case 'b':
			if(m->board[p->endX-1][p->endY-1] == 'w' &&
				m->board[p->endX-2][p->endY-2] == 'e')
			{
				p->flag = 1;
				m->lastmoveX = p->endX-1;
				m->lastmoveY = p->endY-1;
			}else if(m->board[p->endX-1][p->endY+1] == 'w' &&
					m->board[p->endX-2][p->endY+2] == 'e')
			{
				p->flag = 1;
				m->lastmoveX = p->endX-1;
				m->lastmoveY = p->endY+1;
			}
			break;
		case 'W':
			if((m->board[p->endX+1][p->endY+1] == 'b' ||
				m->board[p->endX+1][p->endY+1] == 'B') &&
				m->board[p->endX+2][p->endY+2] == 'e')
			{
				p->flag = 1;
				m->lastmoveX = p->endX+1;
				m->lastmoveY = p->endY+1;
			}else if((m->board[p->endX+1][p->endY-1] == 'b' ||
					m->board[p->endX+1][p->endY-1] == 'B') &&
					m->board[p->endX+2][p->endY-2] == 'e')
			{
				p->flag = 1;
				m->lastmoveX = p->endX+1;
				m->lastmoveY = p->endY-1;
			}else if((m->board[p->endX-1][p->endY-1] == 'b' ||
					m->board[p->endX-1][p->endY-1] == 'B') &&
				m->board[p->endX-2][p->endY-2] == 'e')
			{
				p->flag = 1;
				m->lastmoveX = p->endX-1;
				m->lastmoveY = p->endY-1;
			}else if((m->board[p->endX-1][p->endY+1] == 'b' ||
					m->board[p->endX-1][p->endY+1] == 'B') &&
					m->board[p->endX-2][p->endY+2] == 'e')
			{
				p->flag = 1;
				m->lastmoveX = p->endX-1;
				m->lastmoveY = p->endY+1;
			}
			break;
		case 'B':
			if((m->board[p->endX+1][p->endY+1] == 'w' ||
				m->board[p->endX+1][p->endY+1] == 'W') &&
				m->board[p->endX+2][p->endY+2] == 'e')
			{
				p->flag = 1;
				m->lastmoveX = p->endX+1;
				m->lastmoveY = p->endY+1;
			}else if((m->board[p->endX+1][p->endY-1] == 'w' ||
					m->board[p->endX+1][p->endY-1] == 'W') &&
					m->board[p->endX+2][p->endY-2] == 'e')
			{
				p->flag = 1;
				m->lastmoveX = p->endX+1;
				m->lastmoveY = p->endY-1;
			}else if((m->board[p->endX-1][p->endY-1] == 'w' ||
					m->board[p->endX-1][p->endY-1] == 'W') &&
				m->board[p->endX-2][p->endY-2] == 'e')
			{
				p->flag = 1;
				m->lastmoveX = p->endX-1;
				m->lastmoveY = p->endY-1;
			}else if((m->board[p->endX-1][p->endY+1] == 'w' ||
					m->board[p->endX-1][p->endY+1] == 'W') &&
					m->board[p->endX-2][p->endY+2] == 'e')
			{
				p->flag = 1;
				m->lastmoveX = p->endX-1;
				m->lastmoveY = p->endY+1;
			}
			break;
	}
	printf("fatto\n");
}

void updateLogicMatch(move_message_t *proposal, int eatDestination, match_t *m)
{	
	int startX = proposal->startX;
	int startY = proposal->startY;
	int endX = proposal->endX;
	int endY = proposal->endY;
	int eatX, eatY;
	
	printf("Aggiorno la board..\n");
	// Aggiorno la board
	// Svuoto casella di partenza
	m->board[proposal->startX][proposal->startY] = 'e';
	
	// Svuoto casella "mangiata" e aggiorno contatori e flag vittoria
	if(eatDestination > 0)
	{
		proposal->eat = 1;
		eatX = startX + (endX - startX)/2;
		eatY = startY + (endY - startY)/2;
		m->board[eatX][eatY] = 'e';
		if(proposal->playerMoving == 'w' || proposal->playerMoving == 'W')
		{
			m->board[endX][endY] = proposal->playerMoving;
			m->bpieces--;
			if(m->bpieces == 0)
			{
				m->state = WhiteWin;
				proposal->flag = 5;
			}
		}else if(proposal->playerMoving == 'b' || proposal->playerMoving == 'B')
		{
			m->board[endX][endY] = proposal->playerMoving;
			m->wpieces--;
			if(m->wpieces == 0)
			{
				m->state = BlackWin;
				proposal->flag = 6;
			}
		}
		printf("Svuoto casella mangiata\n");
	}
	
	// Modifico la casella di arrivo della mossa, controllo se potenziare a dama
	switch(proposal->endX)
	{
		case 7:
			if(proposal->playerMoving == 'w')
			{
				m->board[proposal->endX][proposal->endY] = 'W';
				printf("Dama! %c \n", m->board[proposal->endX][proposal->endY]);
			}else m->board[proposal->endX][proposal->endY] = proposal->playerMoving;
			break;
		case 0:
			if(proposal->playerMoving == 'b')
			{
				m->board[proposal->endX][proposal->endY] = 'B';
				printf("Dama! %c \n", m->board[proposal->endX][proposal->endY]);
			}else m->board[proposal->endX][proposal->endY] = proposal->playerMoving;
			break;
		default:
			printf("ora dovrei aggiornare casella di arrivo: %d %d\n", proposal->endX, proposal->endY);
			m->board[proposal->endX][proposal->endY] = proposal->playerMoving;
			break;
	}
	printf("Aggiornato! %c \n", m->board[proposal->endX][proposal->endY]);
	m->lastmoveX = proposal->endX;
	m->lastmoveY = proposal->endY;
	if(m->hasEat != 0)
	{
		canEatMore(proposal, m);
	}
}

// Valuto la correttezza della mossa
int evaluateProposal(move_message_t *proposal, match_t *m)
{	
	int mustEat;
	proposal->eat = 0;
	printf("Valuto la proposal\n");
	// Verifico precondizioni
	if(evalPreConditions(proposal, m->board) == -1)
		return 1;
	if(m->lastmoveX == 0 && m->lastmoveY == 0)
	{
		mustEat = 0;
		m->hasEat = mustEat;
	}else mustEat = evalEat(proposal, m);
	m->hasEat = mustEat;
	int eatDestination = canMove(proposal, mustEat, m->board);
		
	// Verifico la destinazione della mossa
	if(eatDestination == 0)
	{
		return 2;
	}else{
	updateLogicMatch(proposal, eatDestination, m);
	return 0;
	}
}
